#!/usr/bin/python
# -*- coding: utf-8 -*-
from math import *
import pygame
import random
from pygame.locals import *
from sys import exit
from gameobjects.vector2 import Vector2

import mainmenu
from gameover import gameover_screen
from youwin import win_rules

resWidth = 600
resHeight = 500

topBar = 50

brick = []
powerups = []

lives = 2
score = 0

level = 1

class Ball(object):

	def __init__(self,name):
		self.name = name
		self.x = 50
		self.y = 50
		self.vx = 250
		self.vy = -250
		self.speed = 250
		self.radius = 10
		self.direction = Vector2(0, 0)
		self.position = Vector2(350, 330)
		self.angle = 140
		self.velcro = True
		
	def ball_functions(self):
		self.bounce_off_walls()
		self.bounce_off_paddle()
		self.animation()
		self.velcro_function()
		
		while self.angle > 360:
			self.angle = (self.angle - 360)
			
	def bounce_off_walls(self):
		
		# if you're having trouble understanding this, draw it. Seriously, it helps. Or talk to a rubber duck. I did both when figuring this crap out.

		if ((self.position.x - (self.radius) <= 0) ): # if the ball hits the left side of the screen...
			if (self.angle > 180) and (self.angle <= 270):
				self.angle = 180 - (self.angle - 180)
			elif (self.angle > 270) and (self.angle < 360):
				self.angle = 90 - (self.angle - 270)
				
		if ((self.position.x + (self.radius) >= resWidth) ): # if the ball hits the right side of the screen...
			if (self.angle > 0) and (self.angle <= 90):
				self.angle = 360 - self.angle
			elif (self.angle > 90) and (self.angle < 180):
				self.angle = 270 - (self.angle - 90)
				
		if ((self.position.y - (self.radius) <= topBar) ): # if the ball hits the top of the screen...
			if (self.angle > 90) and (self.angle <= 180):
				self.angle = 0 + (180 - self.angle)
			elif (self.angle > 180) and (self.angle < 270):
				self.angle = 360 - (self.angle - 180)
			
		if self.position.y - self.radius > resHeight:
			global lives
			lives -= 1
			if lives < 0:
				global screen
				global score
				start_over = gameover_screen(screen,score)
				if start_over == True:
					game_reset()
			else:
				self.reset()
			
	def bounce_off_paddle(self):
		if (self.position.x > paddle.x) and (self.position.x < (paddle.x + paddle.width)) and (self.position.y > (paddle.y - self.radius)) and (self.position.y < (paddle.y + paddle.height)) and self.speed > 0:
			
			if (self.angle > 270) and (self.angle <= 360):
				self.angle = 180 + (360 - self.angle)
			elif (self.angle >= 0) and (self.angle < 90):
				self.angle = 180 - (self.angle)

			#impact_point = self.position.x - paddle.x
			#max_angle = 250
			#if self.angle > 180 and self.angle <= 270 and impact_point < (paddle.width / 4):
				#percentage_point = impact_point / (paddle.width / 4)
				#self.angle = self.angle + (percentage_point * impact_point)

		

	def animation(self):
		self.direction = Vector2(0, 0)
		self.direction.x = sin(self.angle*pi/180.0)
		self.direction.y = cos(self.angle*pi/180.0)
		self.direction.normalize()
		self.position += self.direction * self.speed * time_passed_seconds
		#if self.check_collision() == True:
			#distance = Vector2.from_points(self.position, tempPos)
			#for count in range(1,distance):
				#self.position += 1
				#if collides:
					#self.bounce(bouncetype)
					#break
		#else:
			#self.position = tempPos
		
		
		#ball.x += time_passed_seconds * ball.vx
		#ball.y += time_passed_seconds * ball.speed
		
	def reset(self):
		self.position.x = paddle.x
		self.position.y = paddle.y - self.radius
		self.speed = 250
		global level
		if level == 2:
			self.speed = 500
		self.angle = 140
		self.velcro = True

	def velcro_function(self):
		if self.velcro == True:
			self.speed = 0
			self.position.x = paddle.x + (paddle.width / 2)
			self.position.y = paddle.y - self.radius
		if event.type == MOUSEBUTTONDOWN:
				self.speed = 300
				self.velcro = False

class Paddle(object):
	
	def __init__(self,name):
		self.name = name
		self.x = 320
		self.y = resHeight * .95
		self.vx = 150
		self.width = 80
		self.height = 15
		
	def movement(self):

		#if pressed_keys[K_LEFT]:
			#paddle.x -= time_passed_seconds * paddle.vx
		#if pressed_keys[K_RIGHT]:
			#paddle.x += time_passed_seconds * paddle.vx
			
		x,y = pygame.mouse.get_pos()
		paddle.x = x - (paddle.width / 2)
		
		if paddle.x + paddle.width > resWidth:
			paddle.x = resWidth - paddle.width
		elif paddle.x < 0:
			paddle.x = 0
			
class Brick(object):
	
	def __init__(self, name):
		self.name = name
		self.x = 0
		self.y = 0
		self.vx = 0
		self.width = 40
		self.height = 20
		self.color = (0,0,0)
		self.score = 16
		
class Powerup(object):
	
	def __init__(self,name):
		self.name = name
		self.x = 400
		self.y = 470
		self.vx = 0
		self.vy = 150
		self.radius = 10
		self.dropChance = 40
		
		
	def powerup_functions(self):
		self.animation()
		self.display()
		self.effects()
		
	def animation(self):
		if (len(powerups) > 0):
			for count in xrange(0,(len(powerups))):
				powerups[count].x += time_passed_seconds * powerups[count].vx
				powerups[count].y += time_passed_seconds * powerups[count].vy
				
				if powerups[count].y > resHeight:
					del powerups[count]
		
	def display(self):
		if (len(powerups) > 0):
			for count in xrange(0,(len(powerups))):
				pygame.draw.circle(screen, (0,150,0), (powerups[count].x,powerups[count].y), powerups[count].radius)
	
	def effects(self):
		if (len(powerups) > 0):
			for count in xrange(0,(len(powerups))):
				if (powerups[count].x > paddle.x) and (powerups[count].x < (paddle.x + paddle.width)) and (powerups[count].y > (paddle.y - powerups[count].radius)) and powerups[count].vy > 0:
					self.apply_effect()
					del powerups[count]
					
	def apply_effect(self):
		choice = random.randint(0,3)
		if choice == 0: #ball_slow
			ball.speed -= 50
			if ball.speed < 100:
				ball.speed = 100
			print "slow"
					
		if choice == 1: #ball_fast
			ball.speed += 50
			if ball.speed > 800:
				ball.speed = 800
			print "fast"
		if choice == 2: #paddle_shrink
			paddle.width -= 10
			if paddle.width < 20:
				paddle.width = 20
			print "shrink"
					
		if choice == 3: #paddle_grow
			paddle.width += 10
			if paddle.width > 160:
				paddle.width = 20
			print "grow"



def quit():
	if pressed_keys[K_ESCAPE]:
		exit()
		
def brick_layer():
	brickCount = 0
	tempX = 0
	tempY = 100
	row = 1
	tempColor = (255,0,0)
	score = 16
	brick.append(0)
	numberOfBricks = 200
	while brickCount <= numberOfBricks:
		if tempX >= resWidth:
			tempX = 0
			tempY += 20
			row += 1
			r,g,b = (tempColor)
			r -= 32
			b += 32
			tempColor = (r,g,b)
			score -= 2
			if row > 8:
				numberOfBricks = brickCount
				del brick[len(brick)-1]
				break
		brick[brickCount] = Brick("brick")
		brick[brickCount].x = tempX
		brick[brickCount].y = tempY
		brick[brickCount].color = tempColor
		brick[brickCount].score = score
		brickCount += 1
		tempX += 40
		brick.append(0)

def brick_show():
	for count in xrange(0,len(brick)):
		pygame.draw.rect(screen, (brick[count].color), Rect((brick[count].x,brick[count].y), (brick[count].width,brick[count].height)))


def brick_colide():
	for z in xrange(0,len(brick)):
		if (((ball.position.x) > (brick[z].x - ball.radius) and (ball.position.x) < (brick[z].x + 4 - ball.radius) or (ball.position.x) > (brick[z].x + brick[z].width - 4 + ball.radius) and (ball.position.x) < (brick[z].x + brick[z].width + ball.radius)) and (ball.position.y) > (brick[z].y - ball.radius) and (ball.position.y) < (brick[z].y + brick[z].height + ball.radius)):
			if (ball.angle > 180) and (ball.angle <= 270):
				ball.angle = 180 - (ball.angle - 180)
			elif (ball.angle > 270) and (ball.angle < 360):
				ball.angle = 90 - (ball.angle - 270)
			elif (ball.angle > 0) and (ball.angle <= 90):
				ball.angle = 360 - ball.angle
			elif (ball.angle > 90) and (ball.angle < 180):
				ball.angle = 270 - (ball.angle - 90)
			brick_break(z)
			break

			
		elif (((ball.position.y) > (brick[z].y - ball.radius) and (ball.position.y) < (brick[z].y + 4 - ball.radius) or (ball.position.y) > (brick[z].y + brick[z].height - 4 + ball.radius) and (ball.position.y) < (brick[z].y + brick[z].height + ball.radius)) and (ball.position.x) > (brick[z].x - ball.radius) and (ball.position.x) < (brick[z].x + brick[z].width + ball.radius)):
			if (ball.angle > 90) and (ball.angle <= 180):
				ball.angle = 0 + (180 - ball.angle)
			elif (ball.angle > 180) and (ball.angle < 270):
				ball.angle = 360 - (ball.angle - 180)
			elif (ball.angle > 270) and (ball.angle <= 360):
				ball.angle = 180 + (360 - ball.angle)
			elif (ball.angle >= 0) and (ball.angle < 90):
				ball.angle = 180 - (ball.angle)
			brick_break(z)
			break
			

def brick_break(z):
	global score
	score += brick[z].score

	del brick[z]
	#drop_power_ups(z)
	#brick[z].x = resWidth+1
	#brick[z].y = 1
	
def drop_power_ups(z):
	if random.randint(0,100) < powerup.dropChance:
		powerups.append(0)
		powerups[len(powerups)-1] = Powerup("powerup")
		powerups[len(powerups)-1].x = brick[z].x
		powerups[len(powerups)-1].y = brick[z].y

		powerup.dropChance = 10
	else:
		powerup.dropChance += 1
		
		
def textGUI():
	scoreString = "Score: %i" % score
	livesString = "Extra Balls: %i" % lives
	screen.blit( font.render(scoreString, True, (255, 255, 255)), (20, 1) )
	screen.blit( font.render(livesString, True, (255, 255, 255)), (380, 1) )

def game_reset():
	ball.reset()
	while len(brick) > 0:
		del brick[len(brick)-1]
	global score
	global lives
	score = 0
	lives = 2
	level = 1
	brick_layer()



ball = Ball("ball")
paddle = Paddle("paddle")

powerup = Powerup("powerup")

pygame.init()


screen = pygame.display.set_mode((resWidth, resHeight), 0, 32)
pygame.display.set_caption("Critter Ball!")

pygame.event.set_allowed(None)
pygame.event.set_allowed(QUIT)
pygame.event.set_allowed(MOUSEBUTTONDOWN)


font = pygame.font.SysFont("arial", 30)

screen.fill((255, 255, 255))

#gameover_screen(screen,score)
mainmenu.main_menu(screen)
clock = pygame.time.Clock()

pygame.event.set_grab(True)
#pygame.mouse.set_visible(False)

game_reset()


while True:
	pressed_keys = pygame.key.get_pressed()

	event = pygame.event.poll()
	if event.type == QUIT:
		exit()
	quit()	
		
	time_passed = clock.tick(60)
	time_passed_seconds = time_passed / 1000.0
	
	paddle.movement()
	
	ball.ball_functions()
	
	screen.fill((0, 0, 0))
	
	paddleRect = Rect((paddle.x,paddle.y),(paddle.width,paddle.height))
	pygame.draw.rect(screen, (255,0,0), paddleRect)
	pygame.draw.circle(screen, (255,0,0), (ball.position), ball.radius)
	
	pygame.draw.rect(screen, (100,100,100), (0,0,800,50))
	
	
	brick_show()
	brick_colide()
	
	x, y = pygame.mouse.get_pos()
	
	textGUI()

	
	powerup.powerup_functions()

	won = win_rules(screen,brick,level)
	if won == True:
		ball.reset()
		lives += 1
		while len(brick) > 0:
			del brick[len(brick)-1]
		brick_layer()
		level += 1

#	x-= mouse_cursor.get_width() / 2
#	y-= mouse_cursor.get_height() / 2
#	screen.blit(mouse_cursor, (x, y))

	pygame.display.update()
	
